var path = require('path');
var http = require('http');
var sio = require('socket.io');
var ss = require('socket.io-stream');
var fs = require('fs');
var config = require('./components/fileupload/config');

var route_upload = require('./routes/upload');
var route_uploadsingle = require('./routes/uploadsingle');
var route_uploadsome = require('./routes/uploadsome');
// var route_download = require('./routes/download');

function Utf8ArrayToStr(array) {
    var out, i, len, c;
    var char2, char3;

    out = "";
    len = array.length;
    i = 0;
    while (i < len) {
        c = array[i++];
        switch (c >> 4) {
            case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
                // 0xxxxxxx
                out += String.fromCharCode(c);
                break;
            case 12: case 13:
                // 110x xxxx 10xx xxxx
                char2 = array[i++];
                out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
                break;
            case 14:
                // 1110 xxxx 10xx xxxx 10xx xxxx
                char2 = array[i++];
                char3 = array[i++];
                out += String.fromCharCode(((c & 0x0F) << 12) |
                    ((char2 & 0x3F) << 6) |
                    ((char3 & 0x3F) << 0));
                break;
        }
    }

    return out;
}

// 将外部传入的http对象、express对象和这里创建的socket.io对象建立关联
var socketio = function (httpServer, app) {
    var io = sio(httpServer);

    // 初始化socket.io的事件监听器
    io.on('connection', function (socket) {
        console.log('a user connected');

        socket.on('disconnect', function () {
            console.log('user disconnected');
        });

        // 如果服务端收到了chat message事件，将收到的内容原样传回给客户端（实现聊天室，对本项目无用）
        socket.on('chat message', function (msg) {
            console.log('message: ' + msg);

            io.emit('chat message', msg);
        });

        // 绑定一个socket.io-stream的事件，接收客户端上传的文件，保存到本地文件系统中
        ss(socket).on('upload file', function (stream, data) {
            var filename = path.basename(data.name);
            var filepath = config.upload.path;
            if (!fs.existsSync(filepath)) {
                fs.mkdirSync(filepath, {recursive: true})
            }
            filename = filepath + '/' + filename;
            stream.pipe(fs.createWriteStream(filename));
        });

        // 收到的客户端发送过来的请求，解析一下请求，转交给具体的路由处理，并实时将处理进度推送给客户端
        socket.on('add request', function (msg) {
            console.log('add request: ' + msg);
            var obj = JSON.parse(msg);
            var filepath = config.upload.path;
            var req = {
                body: {
                    // uploadsingle
                    repo:obj.repo,
                    groupid:obj.groupid,
                    artifactid:obj.artifactid,
                    version:obj.version,
                    restype:obj.restype,
                    classifier:obj.classifier,
                    otherclassifiers:obj.otherclassifiers,
                    // uploadsome
                    depcontent: obj.depcontent
                },
                file: {
                    // upload
                    path: obj.file && filepath + '/' + obj.file.path
                }
            };
            var act = obj.action;
            var routeObj = null;
            if (act == '/uploadsingle') {
                routeObj = route_uploadsingle;
            } else if (act == '/uploadsome') {
                routeObj = route_uploadsome;
            } else if (act == '/upload') {
                routeObj = route_upload;
            }
            if (routeObj != null) {
                // 之前实现的是向所有客户端推送消息，现在改成了只向指定的客户端推送，而且只在连接上了之后才会推送
                routeObj.process_async(req, function (data) {
                    // io.emit('chat message', Utf8ArrayToStr(data));
                    if (io.sockets.connected[socket.id]) {
                        io.sockets.connected[socket.id].emit('chat message', Utf8ArrayToStr(data));
                    }
                }, function (data) {
                    // io.emit('error message', Utf8ArrayToStr(data));
                    if (io.sockets.connected[socket.id]) {
                        io.sockets.connected[socket.id].emit('error message', Utf8ArrayToStr(data));
                    }
                });
            }

        });

    });

    // 给express对象绑定路径，实现一个简单的聊天室页面（对本项目无用）
    app.get('/chat/', function (req, res) {
        res.sendFile(path.join(__dirname, 'chat.html'));
    });

    // 将socket.io对象附加到express对象上，便于后续在外部向socket.io推送数据
    app.set('io', io);
}

module.exports = socketio;
